package com.ali.config;

import com.ali.common.ControllerUri;
import com.ali.dto.Response;
import com.ali.dto.ReturnEnum;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.Claim;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义全局过滤器
 */
@Slf4j
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (!checkToken(exchange)) {
            return fail(exchange);
        }
        return chain.filter(exchange);
    }

    /**
     * 校验token
     */
    private boolean checkToken(ServerWebExchange exchange) {
        ServerHttpRequest httpRequest = exchange.getRequest();
        String path = httpRequest.getPath().value();
        log.info("path：" + path);
        if (ControllerUri.SKIP_CHECK_TOKEN.contains(path)) {
            return true;
        }

        HttpHeaders headers = httpRequest.getHeaders();
        log.info("headers：" + headers);
        List<String> usernames = headers.get("username");
        List<String> tokens = headers.get("token");
        log.info("username：" + usernames);
        log.info("token：" + tokens);
        if (usernames == null || usernames.isEmpty() || tokens == null || tokens.isEmpty()) {
            return false;
        }
        String username = usernames.getFirst();
        String token = tokens.getFirst();
        if (username.isEmpty() || token.isEmpty()) {
            return false;
        }
        //TODO从redis获取token
        try {
            Map<String, Claim> map = JWTUtil.tokenVerify(token);
            if (!Objects.equals(username, map.get("username").asString())) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        //TODOredis中token延长1小时

        return true;
    }

    /**
     * 认证失败
     */
    private Mono<Void> fail(ServerWebExchange exchange) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);

        DataBufferFactory dataBufferFactory = serverHttpResponse.bufferFactory();
        Response<String> response = Response.fail(ReturnEnum.RC999.getCode(), "网关认证失败");
        String responseStr = JSON.toJSONString(response);
        DataBuffer wrap = dataBufferFactory.wrap(responseStr.getBytes(StandardCharsets.UTF_8));
        return serverHttpResponse.writeWith(Flux.just(wrap));
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
